import hashlib
import logging
from blls.base_bll import BaseBLL
from config import REDIS_DATABASE_KEY
from dtos.result import Result
from enumobjects.general_enum import YesOrNoEnum
from libs.redis_wrapper import RedisWrapper
from models.annotation_models.annotation_model import Annotation
from models.label_models.label import Label
from models.project_models.project_model import Project
from models.data_models.data_model import Data
from models.user_models.system_user_model import SystemUsers
from utils.common_util import CommonUtil
import os.path as osp


class DataBLL(BaseBLL):

    def get_data_by_project(self, data):
        # ex_list = [elem.decode('utf-8') for elem in RedisWrapper.lrange(REDIS_DATABASE_KEY+str(data["project_id"]), 0, -1)]
        # if len(ex_list) == 0:
        #     return Result.success_result(message="找不到图片")
        # print('ex_list', ex_list)
        if type(data['project_id']) == str:
            data_info = self.db_session.query(Data).filter(Data.project_id == data['project_id'],
                                                           # Data.data_id.in_(ex_list),
                                                           Data.conform == 1).first()
        else:
            data_info = (self.db_session.query(Data).filter(Data.project_id == data['project_id'],
                                                            # Data.data_id.in_(ex_list),
                                                            Data.conform == 1,
                                                            Data.is_delete == YesOrNoEnum.NO.value)).first()
        labels = self.db_session.query(Label).filter(Label.project_id == data['project_id'],
                                                     Label.is_delete == YesOrNoEnum.NO.value).all()
        label_info = [{
                "color": label.color,
                "created":CommonUtil.convert_timestamp_to_dt(label.create_time),
                "id": label.id,
                "label_id": label.label_id,
                "modified": CommonUtil.convert_timestamp_to_dt(label.last_update_time),
                "name": label.name,
                "project_id": label.project_id,
            }for label in labels]
        data_list = []
        annotations = self.db_session.query(Annotation).filter(Annotation.data_id == data_info.data_id,
                                                              Annotation.is_delete == YesOrNoEnum.NO.value,).all()
        annotation_info = [{
            "annotation_id": ann.annotation_id,
            "created": CommonUtil.convert_timestamp_to_dt(ann.create_time),
            # "data_id": ann.data_id,
            "frontend_id": ann.frontend_id,
            "label": label_info,
            # "label_id": ann.label_id,
            "modified": CommonUtil.convert_timestamp_to_dt(ann.last_update_time),
            # "project_id": ann.project_id,
            "result": ann.result,
            "type": ann.type,
        }for ann in annotations]
        info = {
            "annotations": annotation_info,
             "created": CommonUtil.convert_timestamp_to_dt(data_info.create_time),
             "data_paths": [
             data_info.path
            ],
             "modified": CommonUtil.convert_timestamp_to_dt(data_info.last_update_time),
             "project_id": data_info.project_id,
             "set": data_info.set,
            "data_id": data_info.data_id
        }
        data_list.append(info)
        if data["is_page"] == 0:
            # query, count = self.get_query_and_count(data_info, data['page_size'], data['page_num'])
            res_data = {
                "page_size": data["page_size"],
                "page_num": data["page_num"],
                "count": 1,
                "data": data_list,
            }
            return Result.success_result(data=res_data)
        return Result.success_result(data=data_list)


    def get_data_by_project_2(self, data):
        Data_info = self.db_session.query(Data,SystemUsers.name).outerjoin(SystemUsers,Data.create_user_id == SystemUsers.id).filter(Data.project_id == data['project_id'],
                                                       Data.conform == 1,
                                                       Data.is_delete == YesOrNoEnum.NO.value)
        labels = self.db_session.query(Label).filter(Label.project_id == Project.project_id,
                                                     Label.is_delete == YesOrNoEnum.NO.value).all()
        label_info = [{
            "color": i.color,
            "created": CommonUtil.convert_timestamp_to_dt(i.create_time),
            "id": i.id,
            "label_id": i.label_id,
            "modified": CommonUtil.convert_timestamp_to_dt(i.last_update_time),
            "name": i.name,
            "project_id": i.project_id,
        } for i in labels]
        data_list = []
        if data["is_page"] == 1:
            query = Data_info.all()
        else:
            query, count = self.get_query_and_count(Data_info, data['page_size'], data['page_num'])
            query = query.all()
            if not query:
                return Result.success_result(data=[])
        data_ids = {item[0].data_id for item in query}

        # 2. 批量查询所有未删除的注解
        annotations = self.db_session.query(Annotation).filter(
            Annotation.data_id.in_(data_ids),
            Annotation.is_delete == YesOrNoEnum.NO.value
        ).all()

        # 3. 创建一个字典，将注解按 data_id 分组
        annotation_dict = {}
        for ann in annotations:
            if ann.data_id not in annotation_dict:
                annotation_dict[ann.data_id] = []
            annotation_dict[ann.data_id].append({
                "annotation_id": ann.annotation_id,
                "created": CommonUtil.convert_timestamp_to_dt(ann.create_time),
                "data_id": ann.data_id,
                "frontend_id": ann.frontend_id,
                "label": label_info,  # 确保 label_info 已经定义
                "label_id": ann.label_id,
                "modified": CommonUtil.convert_timestamp_to_dt(ann.last_update_time),
                "project_id": ann.project_id,
                "result": ann.result,
                "type": ann.type,
            })
        # 4. 构建最终结果
        data_list = []
        for item in query:
            annotation_info = annotation_dict.get(item[0].data_id, [])
            info = {
                "annotations": annotation_info,
                "created": CommonUtil.convert_timestamp_to_dt(item[0].create_time),
                "data_paths": [item[0].path],
                "modified": CommonUtil.convert_timestamp_to_dt(item[0].last_update_time),
                "project_id": item[0].project_id,
                "set": item[0].set,
                "data_id": item[0].data_id,
                "create_user_name":item[1],
            }
            data_list.append(info)
        if data["is_page"] == 0:
            query, count = self.get_query_and_count(Data_info, data['page_size'], data['page_num'])
            res_data = {
                "page_size": data["page_size"],
                "page_num": data["page_num"],
                "count": count,
                "data": data_list,
            }
            return Result.success_result(data=res_data)
        return Result.success_result(data=data_list)


    def get_data_num_by_project(self, data):
        count = RedisWrapper.llen(REDIS_DATABASE_KEY+str(data["project_id"]))
        res_data = {
            "finished":count,
        }
        return Result.success_result(data=res_data)

    @staticmethod
    def str2sault(self,seed):
        return hashlib.md5(seed.encode("utf-8")).hexdigest()[:20]

    def get_data_by_data_id_prev(self,data):
        #根据dataid查询Data表数据
        data_info = self.db_session.query(Data).filter(Data.data_id == data["data_id"],
                                                       Data.is_delete == YesOrNoEnum.NO.value).first()
        if not data_info:
            return Result.error_result(data=[],message="图片不见了")
        if not data_info.last_update_time:
            modified_time = None
        else:
            modified_time = CommonUtil.convert_timestamp_to_dt(data_info.last_update_time)
        if not data_info.create_time:
            created = None
        else:
            created = CommonUtil.convert_timestamp_to_dt(data_info.create_time)
        sault = self.str2sault(self, seed=(data_info.path or '') + (created or ''))
        res_data = [
            {
                "created": created,
                "data_id": data_info.data_id,
                "modified": modified_time,
                "path": data_info.path,
                "predicted": "",
                "sault": sault,
                "conform": data_info.conform,
                "size": data_info.size if data_info.size else None,
            }
        ]
        return Result.success_result(data=res_data)

    def get_data_by_data_id(self, data):
        data_id = RedisWrapper.lpop(REDIS_DATABASE_KEY+str(data['project_id']))
        count = RedisWrapper.llen(REDIS_DATABASE_KEY+str(data["project_id"]))
        if count == 0:
            project_info = self.db_session.query(Project).filter(Project.project_id == data['project_id']).first()
            if project_info:
                self.db_session.begin()
                project_info.state = 1
                self.db_session.commit()
        #根据dataid查询Data表数据
        if data['data_id']:
            Data_info = self.db_session.query(Data).filter(Data.data_id == data['data_id'],
                                                           Data.conform == 1,
                                                           Data.is_delete == YesOrNoEnum.NO.value).first()
        else:
            Data_info = self.db_session.query(Data).filter(Data.data_id == data_id,
                                                           Data.conform == 1,
                                                           Data.is_delete == YesOrNoEnum.NO.value).first()
        if not Data_info:
            res_data = [
                {
                    "created": "",
                    "data_id": "",
                    "modified": "",
                    "path": "",
                    "predicted": "",
                    "sault": "",
                    "size": "",
                    "Data_id": ""
                }
            ]
            return Result.error_result(data=res_data,message="没有下一张照片了")
        try:
            self.db_session.begin()
            if not Data_info.create_user_id:
                Data_info.create_user_id = self.get_current_user().id
            self.db_session.commit()
        except Exception as ex:
            message = "原因是：%s" % str(ex)
            logging.info(message)
            self.db_session.rollback()
            return Result.error_result(message=message)
        #根据dataid查询Data表数据
        data_info = self.db_session.query(Data).filter(Data.data_id == Data_info.data_id,Data.is_delete == YesOrNoEnum.NO.value).first()
        if not data_info.last_update_time:
            modified_time = None
        else:
            modified_time = CommonUtil.convert_timestamp_to_dt(data_info.last_update_time)
        if not data_info.create_time:
            created = None
        else:
            created = CommonUtil.convert_timestamp_to_dt(data_info.create_time)
        sault = self.str2sault(self, seed=(data_info.path or '') + (created or ''))
        res_data = [
        {
        "created": created,
        "data_id": data_info.data_id,
        "modified": modified_time,
        "path": data_info.path,
        "predicted": "",
        "sault": sault,
        "conform":data_info.conform,
        "size": data_info.size if data_info.size else None,
        }
]
        return Result.success_result(data=res_data)

    def get_data_image(self, data_id):
        data_obj = self.get_one_obj_by_field('data_id', data_id, Data)
        if not data_obj:
            return Result.error_result(message="未找到data信息")
        project_obj = self.db_session.query(Project).join(Data, Data.project_id == Project.project_id).filter(
            Data.is_delete == YesOrNoEnum.NO.value,
            Data.data_id == data_obj.data_id,
            Project.is_delete == YesOrNoEnum.NO.value
        ).first()
        if not project_obj:
            return Result.error_result(message="未找到项目信息")
        data_dir = project_obj.data_dir
        path = data_obj.path
        folder = CommonUtil.get_path_by_system_version([data_dir, osp.dirname(path)])
        file_name = osp.basename(path)
        file_type = file_name.split('.')[-1]
        file_type_dict = {
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png'
        }
        file_path = CommonUtil.get_path_by_system_version([folder, file_name])
        if not osp.exists(file_path):
            return Result.error_result(message="未找到该文件地址")
        return Result.success_result(data={
            'file_path': file_path,
            'image_type': file_type_dict.get(file_type, 'image/jpeg'),
            'file_name': file_name
        })

    def get_data_image_trimap(self, data_id):
        data_obj = self.get_one_obj_by_field('data_id', data_id, Data)
        if not data_obj:
            return Result.error_result(message="未找到data信息")
        project_obj = self.db_session.query(Project).join(Data, Data.project_id == Project.project_id).filter(
            Data.is_delete == YesOrNoEnum.NO.value,
            Data.data_id == data_obj.data_id,
            Project.is_delete == YesOrNoEnum.NO.value
        ).first()
        if not project_obj:
            return Result.error_result(message="未找到项目信息")
        data_dir = project_obj.data_dir
        path = data_obj.path_2
        folder = CommonUtil.get_path_by_system_version([data_dir, osp.dirname(path)])
        file_name = osp.basename(path)
        file_type = file_name.split('.')[-1]
        file_type_dict = {
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png'
        }
        file_path = CommonUtil.get_path_by_system_version([folder, file_name])
        if not osp.exists(file_path):
            return Result.error_result(message="未找到该文件地址")
        return Result.success_result(data={
            'file_path': file_path,
            'image_type': file_type_dict.get(file_type, 'image/jpeg'),
            'file_name': file_name
        })

